package com.xishu.controller;

import com.xishu.annotation.valid.MethodValidator;
import com.xishu.config.Constant;
import com.xishu.entity.Company;
import com.xishu.entity.NameAndId;
import com.xishu.entity.shop.DiscountTicket;
import com.xishu.entity.shop.Scene;
import com.xishu.entity.shop.Shop;
import com.xishu.entity.shop.ShopTicketMapping;
import com.xishu.response.ResponseData;
import com.xishu.response.ResponseStatus;
import com.xishu.response.VerifyUtil;
import com.xishu.service.*;
import com.xishu.util.ClassUtil;
import com.xishu.util.Tools;
import com.xishu.util.ZipUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static com.xishu.config.Constant.*;

@Api(description = "优惠卷管理")
@RestController
public class DiscountTicketController implements Tools {
    private DiscountTicketService discountTicketService = DiscountTicketService.getInstance();
    private CommonService commonService = CommonService.getInstance();
    private static Logger logger = LoggerFactory.getLogger(DiscountTicketController.class);
    private LockService localLockService = LockService.getInstance();
    public static final int VALID_TYPE_TIME_RANGE = 1;

    @ApiOperation(value = "创建优惠卷")
    @PostMapping(value = ("/user/discount/ticket"), produces = ("application/json;charset=UTF-8"))
    public ResponseData create(@RequestBody DiscountTicket discountTicket) throws Exception {
        VerifyUtil.verify(() -> discountTicket.getCompanyId() != null);
        VerifyUtil.verify(() -> discountTicket.getTicketType() != null);
        VerifyUtil.verify(() -> getBoolean(discountTicket.getTakeout()) || getBoolean(discountTicket.getTangshi()),ResponseStatus.TICKET_TANGSHI_TAKEOUT_SELECT_ONE);
        if (isEmpty(discountTicket.getCompanyName())) {
            discountTicket.setCompanyName(commonService.findEntity(discountTicket.getCompanyId(), Company.class).getName());
        }

        //有绑定时间，那么取消开始时间
        if (discountTicket.getBindingDays() != null && discountTicket.getBindingDays() != 0) {
            discountTicket.setStartTime(null);
            discountTicket.setEndTime(null);
        }

        if (discountTicket.getEndTime() != null) {
            long endTime = discountTicketService.formatEndTime(discountTicket);
            discountTicket.setEndTime(endTime);
        }

        //如果是店长折扣券，不做处理
        if (getLong(discountTicket.getCustomerId()) == WAITER_LEADER_TICKET) {
            //先不校验,添加生成优惠码
            String code = DiscountTicketService.getInstance().generateCode(discountTicket.getCompanyId());
            discountTicket.setCode(code);
        } else if (discountTicket.getTicketType() == Constant.DISCOUNT_TICKET_TYPE_CASH) {
            //满减校验
            VerifyUtil.verify(() -> getLong(discountTicket.getLimitSale()) > 0);
            VerifyUtil.verify(() -> discountTicket.getDiscountCash() > 0);

            if (discountTicket.getValidType() == VALID_TYPE_TIME_RANGE) {
                //如果传了开始结束时间，那么做校验
                if (discountTicket.getEndTime() != null && discountTicket.getStartTime() != null) {
                    VerifyUtil.verify(() -> discountTicket.getEndTime() > discountTicket.getStartTime());
                }
            }

            //金额券，将折扣设计成空
            discountTicket.setDiscount(null);
            VerifyUtil.verify(() -> isNotEmpty(discountTicket.getShopList()));
            VerifyUtil.verify(() -> isNotEmpty(discountTicket.getSceneList()));


        } else if (discountTicket.getTicketType() == Constant.DISCOUNT_TICKET_TYPE_DISCOUNT) {
            //折扣卷校验
            VerifyUtil.verify(() -> getLong(discountTicket.getLimitSale()) > 0);
            VerifyUtil.verify(() -> discountTicket.getDiscount() > 0);

            if (discountTicket.getValidType() == VALID_TYPE_TIME_RANGE) {
                //如果传了开始结束时间，那么做校验
                if (discountTicket.getEndTime() != null && discountTicket.getStartTime() != null) {
                    VerifyUtil.verify(() -> discountTicket.getEndTime() > discountTicket.getStartTime());
                }
            }

            //折扣券，将金额设置成空
            discountTicket.setDiscountCash(null);
            VerifyUtil.verify(() -> isNotEmpty(discountTicket.getShopList()));
            VerifyUtil.verify(() -> isNotEmpty(discountTicket.getSceneList()));


        } else if (discountTicket.getTicketType() == DISCOUNT_TICKET_TYPE_AFTER_COST) {
            //消费后金额券
            VerifyUtil.verify(() -> isNotEmpty(discountTicket.getShopList()));
            VerifyUtil.verify(() -> discountTicket.getAfterCash() != null || discountTicket.getAfterPercent() != null);
            VerifyUtil.verify(() -> isNotEmpty(discountTicket.getSceneList()));
            VerifyUtil.verify(() -> isNotEmpty(discountTicket.getAfterSceneList()));
            VerifyUtil.verify(() -> getInt(discountTicket.getAfterValidDay()) >= 0);


        } else if (getBoolean(discountTicket.getItemTicket())) {
            //菜品券
            VerifyUtil.verify(() -> isNotEmpty(discountTicket.getMainItemIdList()));

        }

        //如果是线上券，设置成已生成
        if (getBoolean(discountTicket.getOnlineTicket())) {
            discountTicket.setStatus(TICKET_GENERATED);
        }

        //如果是消费后金额券，也改成已生成
        if (discountTicket.getTicketType() == DISCOUNT_TICKET_TYPE_AFTER_COST) {
            discountTicket.setStatus(TICKET_GENERATED);
        }

        discountTicket.setTemplate(true);
        ZhEnService.getInstance().dealZhEn(discountTicket);

        return CommonService.getInstance().createObject(discountTicket, (t) -> {
            //店长优惠券不做处理
            if (getLong(t.getCustomerId()) != WAITER_LEADER_TICKET) {
                DiscountTicketService.getInstance().createMapping(t);
            }
        });
    }

    @ApiOperation(value = "生成优惠卷")
    @PostMapping(value = ("/user/discount/ticket/generate"), produces = ("application/json;charset=UTF-8"))
    public ResponseData generate(@RequestBody DiscountTicket reqDiscountTicket) throws Exception {
        VerifyUtil.verify(() -> reqDiscountTicket.getId() != null);
        DiscountTicket discountTicket = DiscountTicketService.getInstance().findTicket(reqDiscountTicket.getId());

        VerifyUtil.verify(() -> !getBoolean(discountTicket.getDownloaded()), ResponseStatus.DISCOUNT_TICKET_DOWNLOAD);

        //把优惠卷的状态改成生成中
        discountTicket.setStatus(TICKET_GENERATING);
        commonService.save(discountTicket);

        //先把已经有的优惠卷删除了
        List<DiscountTicket> discountTicketList = DiscountTicketService.getInstance().findDiscountTicketByParentId(discountTicket.getId());
        for (DiscountTicket ticket : discountTicketList) {
            commonService.delete(ticket);
        }

        //依次创建对应数量的优惠卷
        String lockKey = "discount.ticket.service" + discountTicket.getCompanyId();
        Object lock = localLockService.getLock(lockKey);
        synchronized (lock) {
            DiscountTicket discountTicketClone = (DiscountTicket) ClassUtil.clone(discountTicket);
            discountTicketClone.setCanExchange(true);

            for (int i = 0; i < discountTicket.getLimitSale(); i++) {
                discountTicketService.createRealTicket(discountTicketClone);
            }

            //全部成功生成之后，变成已生成
            discountTicket.setStatus(TICKET_GENERATED);
            commonService.save(discountTicket);
        }

        return ResponseData.emptyResponse();
    }

    /**
     * 批量先生成HTML，打包上传，如果已经存在的情况下，那么不用再生成了
     *
     * @param reqDiscountTicket
     * @return
     * @throws Throwable
     */
    @ApiOperation(value = "下载优惠卷，如果上次的存在了，直接下载")
    @PutMapping(value = ("/user/discount/ticket/download"), produces = ("application/json;charset=UTF-8"))
    public ResponseData download(@RequestBody DiscountTicket reqDiscountTicket) throws Throwable {
        Long discountTicketId = reqDiscountTicket.getId();
        VerifyUtil.verify(() -> discountTicketId != null);
        DiscountTicket discountTicketInDb = DiscountTicketService.getInstance().findTicket(discountTicketId);
        boolean ownCompany = CompanyService.getInstance().ownCompany(discountTicketInDb.getCompanyId());
        VerifyUtil.verify(() -> ownCompany);
        logger.info("title msg is {}", reqDiscountTicket.getTitleMsg());
        logger.info("contentDescription is {}", reqDiscountTicket.getContentDescription());

        reqDiscountTicket.setDownloaded(true);
        boolean zh = reqDiscountTicket.getLang() == null || reqDiscountTicket.getLang().equalsIgnoreCase("zh") || reqDiscountTicket.getLang().equalsIgnoreCase("zhTW");

        VerifyUtil.verify(() -> getInt(discountTicketInDb.getStatus()) == TICKET_GENERATED, ResponseStatus.GENERATE_DISCOUNT_TICKET_FIRST);

        List<DiscountTicket> discountTicketList = DiscountTicketService.getInstance().findDiscountTicketByParentId(discountTicketId);
        VerifyUtil.verify(() -> isNotEmpty(discountTicketList), ResponseStatus.GENERATE_DISCOUNT_TICKET_FIRST);

        logger.info("discount ticket size is {}", discountTicketList.size());
        //找一个优惠卷来查询公司信息
        Long companyId = discountTicketList.get(0).getCompanyId();
        Company company = commonService.findEntity(companyId, Company.class);

        ArrayList<File> ticketFileList = new ArrayList<>();
        List<DiscountTicket> ticketList = new ArrayList<>();
        //如果是横版的，那么是3张一组
        int size = 0;
        int index = 1;
        for (DiscountTicket ticket : discountTicketList) {
            size = size + 1;
            ticket.setContentDescription(reqDiscountTicket.getContentDescription().replace("\n", "<br/>"));
            ticket.setTitleMsg(reqDiscountTicket.getTitleMsg());
            ticketList.add(ticket);

            if (size >= 300) {
                logger.info("size is gt 300");
                if (getInt(reqDiscountTicket.getDownloadType()) == DISCOUNT_TICKET_DOWNLOAD_TYPE_HORIZONTAL) {
                    ticketFileList.add(discountTicketService.generateHorizontalTicketFile(ticketList, company, index, zh));
                } else {
                    ticketFileList.add(discountTicketService.generateVerticalTicketFile(ticketList, company, index, zh));
                }

                size = 0;
                ticketList.clear();
                index = index + 1;
            }

            logger.info("size is {}", size);
            continue;
        }

        //超过部分，再添加
        if (!ticketList.isEmpty()) {
            if (getInt(reqDiscountTicket.getDownloadType()) == DISCOUNT_TICKET_DOWNLOAD_TYPE_HORIZONTAL) {
                ticketFileList.add(discountTicketService.generateHorizontalTicketFile(ticketList, company, index, zh));
            } else {
                ticketFileList.add(discountTicketService.generateVerticalTicketFile(ticketList, company, index, zh));
            }
        }

        File zipFile = ZipUtil.zip(ticketFileList);
        //上传到阿里云
        ObjectService.getInstance().uploadObject(zipFile);
        commonService.updateObject(reqDiscountTicket);

        return commonService.createResponse(zipFile.getName());
    }

    @ApiOperation(value = "修改优惠卷")
    @PutMapping(value = ("/user/discount/ticket/modify"), produces = ("application/json;charset=UTF-8"))
    public ResponseData modify(@RequestBody DiscountTicket reqDiscountTicket) throws Exception {
        //已经下载过的优惠卷是不能够再修改的
        DiscountTicket discountTicketInDb = discountTicketService.findTicket(reqDiscountTicket.getId());
//        VerifyUtil.verify(() -> !getBoolean(discountTicketInDb.getDownloaded()), ResponseStatus.DISCOUNT_TICKET_DOWNLOAD);
        boolean ownCompany = CompanyService.getInstance().ownCompany(discountTicketInDb.getCompanyId());
        VerifyUtil.verify(() -> ownCompany);

        //没有下载过的优惠券，强制改成未生成
        if (!getBoolean(discountTicketInDb.getDownloaded())) {
            reqDiscountTicket.setStatus(0);
        }

        //有绑定时间，那么取消开始时间
        if (getInt(discountTicketInDb.getBindingDays()) != 0) {
            discountTicketInDb.setStartTime(null);
            discountTicketInDb.setEndTime(null);
        }

        if (discountTicketInDb.getEndTime() != null) {
            long endTime = discountTicketService.formatEndTime(discountTicketInDb);
            discountTicketInDb.setEndTime(endTime);
        }

        return CommonService.getInstance().updateObject(reqDiscountTicket, (ticket -> {
            //先将以前的优惠卷删除掉，再重新生成
            if (discountTicketInDb.getTicketType() == Constant.DISCOUNT_TICKET_TYPE_AFTER_COST) {
                //消费后的删除映射，重新映射
                ShopTicketMapping shopTicketMapping = new ShopTicketMapping();
                shopTicketMapping.setTicketId(discountTicketInDb.getId());
                //直删
                try {
                    commonService.delete(shopTicketMapping, false, null);
                } catch (Exception e) {
                    logger.error("e", e);
                }

                //重新映射
                DiscountTicketService.getInstance().createMapping(discountTicketInDb);
            }
        }));
    }

    @ApiOperation(value = "查询优惠卷")
    @PutMapping(value = ("/user/discount/ticket"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData find(@RequestBody DiscountTicket discountTicket) throws Exception {
        DiscountTicket discountTicketInDb = commonService.searchOne((DiscountTicket) ClassUtil.clone(discountTicket));

        if (discountTicketInDb != null) {
            Long companyId = discountTicketInDb.getCompanyId();
            CompanyService.getInstance().ownCompany(companyId);
        }

        //如果是要查询模板，那么判断有没有传customerId,如果没有传customerId,做特殊查询
        if (getBoolean(discountTicket.getTemplate())) {
            if (discountTicket.getCustomerId() == null) {
                discountTicket.setCustomerIdNotExist(true);
            }
        }

        return CommonService.getInstance().searchResponse(discountTicket, (t) -> {
            try {
                discountTicketService.syncParentTicket(t);
                t.setExpiredTime(t.getEndTime());

                List<NameAndId> list = getList(t.getShopList());
                for (NameAndId nameAndId : list) {
                    Long shopId = nameAndId.getId();
                    Shop shop = ShopService.getInstance().findShopById(shopId);
                    nameAndId.setName_zh(shop.getName_zh());
                    nameAndId.setName_en(shop.getName_en());
                }

                if (isEmpty(t.getName_zh())) {
                    t.setName_zh(t.getName());
                }

                if (isEmpty(t.getName_en())) {
                    t.setName_en(t.getName());
                }

                //如果是菜品券，查询相关的菜的名称
                discountTicketService.addCompanyMainItemList(t);

                //查询对应的场景
                List<NameAndId> sceneList = getList(t.getSceneList());
                for (NameAndId nameAndId : sceneList) {
                    Long sceneId = nameAndId.getId();
                    Scene scene = SceneService.getInstance().findScene(sceneId);
                    nameAndId.setName(scene.getName());
                    nameAndId.setName_zh(scene.getName());
                    nameAndId.setName_en(scene.getName());
                }

            } catch (Exception e) {
                logger.error("e", e);
            }
        });
    }

    @ApiOperation(value = "删除优惠卷")
    @DeleteMapping(value = ("/user/discount/ticket"), produces = ("application/json;charset=UTF-8"))
    public ResponseData delete(@RequestBody DiscountTicket discountTicket) throws Exception {
        //添加校验
        VerifyUtil.verify(() -> discountTicket.getId() != null || isNotEmpty(discountTicket.getIds()));
        //根据优惠卷的id找到归属于那个公司
        DiscountTicket discountTicketInDb = findTicket(discountTicket.getId());
        discountTicket.setCompanyId(discountTicketInDb.getCompanyId());
        //验证是否在使用优惠卷
        DiscountTicketService.getInstance().verifyTicketInUse(discountTicket);

        return CommonService.getInstance().delete(discountTicket, true, (ticket -> {
            ticket.setFlagDelete(true);
            DiscountTicket parentTicket = commonService.searchOne(ticket);

            //删除相关的优惠卷
            DiscountTicket reqTicket = new DiscountTicket();
            reqTicket.setParentId(parentTicket.getId());

            try {
                commonService.delete(reqTicket, true);
            } catch (Exception e) {
                logger.error("e", e);
            }

            if (parentTicket.getTicketType() == Constant.DISCOUNT_TICKET_TYPE_AFTER_COST) {
                //如果是金额消费后，删除映射关系
                try {
                    DiscountTicketService.getInstance().deleteMapping(parentTicket);
                } catch (Exception e) {
                    logger.error("e", e);
                }
            }

            //删除会员里面的券
            if (discountTicketInDb != null) {
                CustomerService customerService = CustomerService.getInstance();
                customerService.deleteCustomerTicket(discountTicketInDb.getCompanyId(), discountTicketInDb.getId());
            }

        }));
    }

    public DiscountTicket findTicket(Long ticketId) throws Exception {
        if (ticketId == null) {
            return null;
        }

        return DiscountTicketService.getInstance().findTicket(ticketId);
    }

}
